class Rogaru::Tilemap::Map
	def initialize()
		@layer_count = 0
		@layers = []
		@tiles  = [] 
		# These tiles will be shared between the map and all it's layers. 
		# Tiles with negative index will be skipped.  
		@moving_tiles  = [ ] 
		@x 	= 0
		@y 	= 0
		@vx = 0
		@vy = 0
		@maxwide 		= 0
		@maxhigh 		= 0
		@maxtilehigh 	= 0
		@maxtilewide 	= 0
		@entities       = []
	end	
	
	attr_accessor :entities
	
	def update(screen_wide, screen_high)
		@x += vx
		@y += vy
		@x = 0 if @x < 0
		@y = 0 if @y < 0
		limit_x = @maxwide - screen_wide
		limit_y = @maxhigh - screen_high
		@y = limit_y if @y > limit_y
		@x = limit_x if @x > limit_x
	end
	
	def advance
		@moving_tiles.each { | tile | tile.advance }
	end

	def add_tile(tile) 
		@tiles.push tile
		@moving_tiles.push tile if(tile.animated?)
		return @tiles.size - 1
	end
	
	def get_tile(index) 
		return @tiles[index]
	end

	def add_layer(layer)
		layer.set_tiles @tiles
		@layers.push layer
		@layer_count += 1 
		if @maxwide < layer.w then
			@maxwide 		= layer.w 
			@maxtilewide 	= layer.tw
		end
		if @maxhigh < layer.h then
			@maxhigh 		= layer.h 
			@maxtilehigh 	= layer.th
		end
	end
	
	def new_layer(wide, high, tilewide = 40, tilehigh = 40)
		layer = Tilemap::Layer.new(self, wide, high, tilewide, tilehigh)
		self.add_layer(layer)
	end
	
	def draw_parallax_auto(screen)
		self.draw_parallax(screen, @x, @y)
	end
	
	def draw_auto(screen)
		self.draw(screen, @x, @y)
	end
	
	attr_accessor :vx
	attr_accessor :vy
	attr_reader :x
	attr_reader :y

	def tw()
		return @maxtilewide
	end

	def th()
		return @maxtilehigh
	end
	
	def draw_parallax(screen, x, y)
		top = @layers.last
		top_w = top.w
		top_h = top.h
		@layers.each do
			|layer|	
			x_scale = (layer.w - screen.w).to_f  / top_w
			y_scale = (layer.h - screen.h).to_f  / top_h
			x_draw  = (x * x_scale).to_i
			y_draw  = (y * y_scale).to_i
			layer.draw(screen, x_draw, y_draw)
		end
	end
	
	def draw(screen, x, y)
		index = 0
		@layers.each do
			|layer|	
			layer.draw(screen, x, y)
			if index == 0 then
				@entities.each { |entity| entity.draw(screen, x, y ) }
				index += 1
			end
		end
	end


	def draw_with_effects(screen, x, y)
		@layers.each do
			|layer|	
			layer.draw(screen, x, y)
			layer.draw_effects(screen, x, y)
		end
	end
	
	def draw_auto_with_effects(screen)
		draw_with_effects(screen, @x, @y)
	end
	
	def to_xml()
		map   = REXML::Element.new 'map'
		tiles = map.add_element 'tiles'
		for i in (0...@tiles.size)
			tile = @tiles[i].to_xml()
			tile.add_attribute('index', i.to_s)
			tiles.add_element(tile)
		end
		layers = map.add_element 'layers'
		for i in (0...@layers.size)
			layer = @layers[i].to_xml()
			layer.add_attribute('z', i.to_s)
			layers.add_element(layer)
		end
		return map
	end
	
	def self.new_from_xml(xml)
		map = Tilemap::Map.new()
		xml.elements.each('*/tiles/tile') do | xml_tile | 
			tile = Tilemap::Tile.new_from_xml(xml_tile)
			map.add_tile(tile)
		end
		xml.elements.each('*/layers/layer') do | xml_layer |
			layer = Tilemap::Layer.new_from_xml(xml_layer, map)
			map.add_layer(layer)
		end
		return map
	end
	
	def self.load_from(filename)
		doc = REXML::Document.new File.new(filename)
		return self.new_from_xml(doc)
	end
	
	def save_to(filename) 
		xml = self.to_xml 
		# Do conversion first, so the map is not clobbered in case it bombs.
		File.open(filename, 'w') do |file|
                  formatter = REXML::Formatters::Pretty.new( 1, false )
                  formatter.write xml, file
		end
	end
	
	def screen_to_tile_x(layer_index, screen_x)
		@layers[layer_index].screen_to_tile_x(@x, screen_x)
	end 
	
	def screen_to_tile_y(layer_index, screen_y)
		@layers[layer_index].screen_to_tile_y(@y, screen_y)
	end 

	def tile_to_screen_x(layer_index, tile_x)
		@layers[layer_index].tile_to_screen_x(@x, tile_x)
	end 
	
	def tile_to_screen_y(layer_index, tile_y)
		@layers[layer_index].tile_to_screen_y(@y, tile_y)
	end 
	
	def tile_count
		return @tiles.size
	end
	
	def layer_count
		return @layers.size
	end

	def set(x, y , z, tile_id) 
		layer = @layers[z]
		return nil if layer.nil?
		layer.set(x, y, tile_id)
	end
	
	def get(x, y , z) 
		layer = @layers[z]
		return nil if layer.nil?
		layer.get(x, y)
	end
	
end